Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reopen log file on SIGHUP #917

Merged
merged 2 commits into from May 21, 2012
Merged

Reopen log file on SIGHUP #917

merged 2 commits into from May 21, 2012

Conversation

mndrix
Copy link
Contributor

@mndrix mndrix commented Mar 5, 2012

This pull request is intended to facilitate bitcoind log rotation. When the daemon receives a HUP signal, it reopens the debug.log file so the previous one can be rotated. I've tried to describe the technical motivation in each of the three commit messages. It uses flockfile and funlockfile to avoid thread contention issues. As best I can tell, those functions are available on most platforms, but I have only compiled on OS X.

I have a test script which sends SIGHUP to the bitcoind process every 100 ms. I've been running with that test script and this patch for the last few days and haven't had any problems. In my tests, it behaves well during startup and shutdown too. Each rotated log contains the content I expect.

Suggestions for improvement welcome.

@sipa
Copy link
Member

sipa commented Mar 5, 2012

Will this compile on windows/OSX/...?

@mndrix
Copy link
Contributor Author

mndrix commented Mar 5, 2012

It does compile on OS X. I don't have a Windows build machine, but Microsoft documentation suggests that they support the necessary APIs.

@luke-jr
Copy link
Member

luke-jr commented Mar 14, 2012

"Microsoft Windows Services for UNIX" != Windows. flockfile is not available on Windows (or at least not for MingW), and compiling it in next-test fails...

@mndrix
Copy link
Contributor Author

mndrix commented Mar 14, 2012

I'll update the pull request to only activate flockfile and funlockfile when #ifndef WIN32. We already do that for signal handlers.

One could also try using CreateMutex and WaitForSingleObject to support similar locking semantics on Windows. I don't have a Windows development machine, so I'd be coding blind trying to implement that approach.

@luke-jr
Copy link
Member

luke-jr commented Mar 14, 2012

"Nobody" has a Windows development machine. Windows builds are produced with gitian on Ubuntu.

@mndrix
Copy link
Contributor Author

mndrix commented Mar 14, 2012

I've updated the branch so that it's a noop on Windows

char pszFile[MAX_PATH+100];
GetDataDir(pszFile);
strlcat(pszFile, "/debug.log", sizeof(pszFile));
const char* pszFile = GetDebugLogName().c_str();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Won't the std::string temporary from GetDebugLogName() free pszFile before it is used?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know. I've not encountered any problems running with this code. My C++ chops are weak, so I'll gladly do this differently if there's a better way.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the equivalent of (in C):

char *s = malloc(8);
memcpy(s, "testing", 8);
free(s);
fopen(s, "a");

Try this:

std::string file = GetDebugLogName();
fileout = fopen(file.c_str(), "a");

@mndrix
Copy link
Contributor Author

mndrix commented Apr 13, 2012

Thanks to ee12c3d the problem @luke-jr mentioned is no longer an issue. I've updated the pull request accordingly.

@luke-jr
Copy link
Member

luke-jr commented Apr 14, 2012

ACK. Planning to (user-optionally) merge this in Gentoo for logrotate support.

@laanwj
Copy link
Member

laanwj commented Apr 16, 2012

Looks like a useful feature.

How does this interact with the log rotation / debug.log size-limiting inside bitcoin itself? I remember seeing some code for that.

@mndrix
Copy link
Contributor Author

mndrix commented Apr 16, 2012

I don't know of any log rotation code inside bitcoin, but this code works well with the size limiting code. ShrinkDebugFile() runs only during startup before debug.log is opened for writing.

@laanwj
Copy link
Member

laanwj commented Apr 16, 2012

Ok, so that only runs at startup. That's good.

ACK

@rebroad
Copy link
Contributor

rebroad commented Apr 17, 2012

-1 from me. I think bitcoin should re-examine the bitcoin.conf file upon receiving a HUP. This, AFAIK is the more standard thing to happen on Unix, isn't it?

@laanwj
Copy link
Member

laanwj commented Apr 18, 2012

The one does not exclude the other. And keep your -1/+1 out of here please.

@rebroad
Copy link
Contributor

rebroad commented Apr 18, 2012

@laanwj You mean rotate the log file and re-parse bitcoin.conf? -0.99999 to that one ;)

@laanwj
Copy link
Member

laanwj commented Apr 18, 2012

Yes. That's what most daemons do AFAIK and is sane. Both reopening the log
file and re-reading the config file are no-ops if nothing changed to the
log file and configuration file respectively.

@rebroad
Copy link
Contributor

rebroad commented Apr 18, 2012

I think it makes more sense to have a config option to specify how many logs files to keep and how often to rotate them. Having the log file rotated every time you want to re-read the config would be not very useful IMHO, as there may be 10000 lines added since the last config change or only 10 lines.

@laanwj
Copy link
Member

laanwj commented Apr 18, 2012

I see no reason at all to include log rotation into bitcoin itself.

There are excellent log rotation tools in common use. The only support they
require of the application is reopening the log on a signal (like this pull
request does). These have settings to rotate by size, by time, to
autocompress old files, and so on.

@rebroad
Copy link
Contributor

rebroad commented Apr 18, 2012

@laanwj I'm not aware of many people using Windows XP (for example) that use log rotation tools, and even if they did, are the tools able to rotate the logs at exactly midnight so that entries from either side of midnight don't end up in the wrong log file?

@Flowdalic
Copy link
Contributor

I would recommend using SIGHUP for config file reloading and SIGUSR1 for logrotation. This is how most daemons do it and how it should be used with logrotate. That's whats needed for the Gentoo ebuild logrotate use flag and I am sure other distributions would benefit from it too. Rotation of log files should not be done by bitcoind. I am sure there are solutions for win32 users also.

@mndrix
Copy link
Contributor Author

mndrix commented Apr 18, 2012

All three examples in the logrotate man page use SIGHUP. The default signal for newsyslog (used on OS X and other BSDs) is SIGHUP. As best I can tell, that's the closest thing to a standard that exists.

@Flowdalic
Copy link
Contributor

On the other hand, many prominent FOSS uses SIGUSR1:

  • apache
  • mongodb
  • dovecot

And my expectation about signals and daemons is that SIGHUP reloads the config file and SIGUSR1 re-opens the log file. Since both actions are not really related to each other, this seems to be a saner approach. And the stackoverflow answer shows that the community thinks so too.

@luke-jr
Copy link
Member

luke-jr commented Apr 18, 2012

All those FOSS you just listed also use USR1 for reloading configs...

But can we just pick one, any one, or maybe even both, and not spend pages discussing the pros/cons of each?

@davout
Copy link

davout commented Apr 18, 2012

IMHO configuration hot-reload isn't very useful... just my two satoshis...
On the other hand log file reopening would be really nice to have

@rebroad
Copy link
Contributor

rebroad commented Apr 18, 2012

@davout I agree that at present config reload isn't very useful. I'm tempted to suggest that SIGHUP be reserved for that possibly functionality in future though, and going with SIGUSR1 for the logfile rotation, if that's the agreed standard. e.g. how does "tor" do things?

I still think it's not unreasonable for bitcoin to offer to do it's own log rotation though - people can still choose to use a 3rd party program if they prefer. one or two config options would probably suffice, and it'd be easy to code.

@davout
Copy link

davout commented Apr 18, 2012

@rebroad it is unreasonable to reinvent the wheel. if you don't care about log rotation you'll be fine with the log size limit. if you do care you'll use logrotate.

@laanwj
Copy link
Member

laanwj commented Apr 19, 2012

@rebroad: We want to reduce the complexity of the core, not increase it. Anything that can (sanely) be handled by external utilities, should be. If your platform does not have these utilities, you can port them or switch platform.

Note that log rotation is only useful for servers and services, in which you'd like to keep the old data for auditing purposes. Windows XP users tend to be normal end-users which don't care about log files at all.

Reloading configuration is an orthogonal option, open a new issue and discuss about it there.

Let's keep this thread for testing and ACKing this code.

@jgarzik
Copy link
Contributor

jgarzik commented May 8, 2012

  1. Reloading config file is very common daemon behavior
  2. Reloading config file is very complex, and far beyond the scope of this pull request
  3. Log rotation is beyond the scope of this pull request.
  4. ACK this pull request, in concept. See code comments for minor nits.

Let's get this merged.

@jgarzik
Copy link
Contributor

jgarzik commented May 8, 2012

Code review comments:

  1. Is freopen(3) guaranteed to always return orig_stream? It seems unwise to discard the !NULL return value, if not downright incorrect.

  2. The "locking" is definitely disappointing... using file locks, which often depend on filesystem-specific behavior, due to lack of CRITICAL_SECTION() is decidedly suboptimal. I'm certain that boost has a thread locking primitive that may be statically initialized, and available immediately at startup.

@laanwj
Copy link
Member

laanwj commented May 9, 2012

I assumed that the point of using file locks is you can block the logger from your log rotation tool, so you don't lose log records during the transition?

@mndrix
Copy link
Contributor Author

mndrix commented May 9, 2012

1) Is freopen(3) guaranteed to always return orig_stream?

My understanding of the documentation on Linux and OS X, leads me to say yes.

I'm certain that boost has a thread locking primitive that may be statically initialized, and available immediately at startup

I've not found such a primitive in the Boost libraries, but may not recognize it if I saw it. I'll gladly change the locking technique if someone can point me at a better primitive.

@jgarzik
Copy link
Contributor

jgarzik commented May 15, 2012

  1. Agreed, freopen(stream) returns stream. ACK there.

  2. As one would expect, boost::mutex is a proper C++ class, and is available properly initialized (unlocked) as soon as the class is instantiated. Here is a non-threaded working example: https://gist.github.com/2702335

@mndrix
Copy link
Contributor Author

mndrix commented May 18, 2012

Rebased and updated to use boost::mutex

@jgarzik
Copy link
Contributor

jgarzik commented May 18, 2012

Changes look good, except for one: you made 'fileout' a global variable, when the existing, more narrowly-scoped 'static' declaration is preferred.

Might consider making that static mutex more narrowly scoped like 'fileout', too.

Acquire an exclusive, advisory lock before sending output to debug.log
and release it when we're done. This should avoid output from multiple
threads being interspersed in the log file.

We can't use CRITICAL_SECTION machinery for this because the debug log
is written during startup and shutdown when that machinery is not
available.

(Thanks to Gavin for pointing out the CRITICAL_SECTION problems based
on his earlier work in this area)
The best log rotation method formerly available was to configure
logrotate with the copytruncate option.  As described in the logrotate
documentation, "there is a very small time slice between copying the
file and truncating it, so some logging data might be lost".

By sending SIGHUP to the server process, one can now reopen the debug
log file without losing any data.
@mndrix
Copy link
Contributor Author

mndrix commented May 18, 2012

Good suggestions. Updated.

@jgarzik
Copy link
Contributor

jgarzik commented May 18, 2012

ACK, looks perfect to me. Thanks for your patience.

sipa added a commit that referenced this pull request May 21, 2012
@sipa sipa merged commit 63407fd into bitcoin:master May 21, 2012
coblee referenced this pull request in litecoin-project/litecoin Jul 17, 2012
suprnurd pushed a commit to chaincoin-legacy/chaincoin that referenced this pull request Dec 5, 2017
8ee7b8a Move broadcast creation to CMasternodeBroadcast
lateminer pushed a commit to lateminer/bitcoin that referenced this pull request Oct 30, 2019
342f034 Disable known failing regression tests (Fuzzbawls)
a5f887b [Travis] Update TravisCI from upstream (Fuzzbawls)

Tree-SHA512: 0cf866696ffb6cff539a1412c95f1f10a6e031629f153aa9a01b5326b77bc7de53912c36d254c859e437d7c3035f466d3b3db79aab26cec4767c75e45e16559a
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Sep 8, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants